﻿using System;
using System.Collections.Generic;
using System.Linq;
using LeRenard.Libraries.Templating.Templating;
using LeRenard.Libraries.Templating.Templating.Mapping;
using Xunit;
using LeRenard.Libraries.Templating.Templating.Mapping.Fakes;

namespace LeRenard.Libraries.Templating.Tests
{
    class NonGenericTemplateTests
    {
        [Fact]
        public void TestConstructorWithEmptyString()
        {
            // Arrange
            // Act
            Assert.ThrowsDelegate sut =
            () =>
            {
                var genericTemplate = new NonGenericTemplate(String.Empty);
            };

            // Assert
            Assert.Throws<ArgumentNullException>(sut);
        }

        [Fact]
        public void TestTemplateString()
        {
            // Arrange
            var templateString = "template";
            var sut = new NonGenericTemplate(templateString);

            // Act
            var result = sut.TemplateString;

            // Assert
            Assert.Equal<string>(templateString, result);
        }

        [Fact]
        public void TestGenericParameter()
        {
            // Arrange
            var sut = new NonGenericTemplate("template");

            // Act
            // Assert
            Assert.IsType<NonGenericTemplate>(sut);
        }

        [Fact]
        public void TestMapThrowsArgumentNullException()
        {
            // Arrange
            var sut = new NonGenericTemplate("template");

            // Act
            Assert.ThrowsDelegate resultEmptyString =
            () =>
            {
                sut.Map(String.Empty);
            };
            Assert.ThrowsDelegate resultWhiteSpaceString =
            () =>
            {
                sut.Map("   ");
            };
            Assert.ThrowsDelegate resultNull =
            () =>
            {
                sut.Map(null);
            };

            // Assert
            Assert.Throws<ArgumentNullException>(resultEmptyString);
            Assert.Throws<ArgumentNullException>(resultWhiteSpaceString);
            Assert.Throws<ArgumentNullException>(resultNull);
        }

        [Fact]
        public void TestMapReturnsCorrectTemplateMappingBuilder()
        {
            // Arrange
            var sut = new NonGenericTemplate("template");

            // Act
            var result = sut.Map("placeholder");

            // Assert
            Assert.True(result is INonGenericTemplateMappingBuilder);
        }

        [Fact]
        public void TestMapStoresTemplateMapping()
        {
            // Arrange
            var sut = new NonGenericTemplate("template");

            // Act
            sut.Map("placeholder").To("value");

            // Assert
            Assert.Equal<int>(1, ((List<ITemplateMapping>)sut.TemplateMappings).Count);
        }

        [Fact]
        public void TestGetProcessedTemplate()
        {
            // Arrange
            var constantString = "constant";
            var dateString = DateTime.Now.ToShortDateString();
            var sut = new NonGenericTemplate("{date} {constant}");

            // Act
            sut.Map("{date}").To(() => DateTime.Now.ToShortDateString());
            sut.Map("{constant}").To(constantString);
            var result = sut.GetProcessedTemplate();
            var expected = String.Format("{0} {1}", dateString, constantString);

            // Assert
            Assert.Equal<string>(expected, result);
        }

        [Fact]
        public void TestTemplateMappingsIsCreatedOnConstruction()
        {
            // Arrange
            var sut = new NonGenericTemplate("template");

            // Act
            // Assert
            Assert.NotNull(sut.TemplateMappings);
            Assert.Equal<int>(0, ((List<ITemplateMapping>)sut.TemplateMappings).Count);
        }

        [Fact]
        public void TestTemplateMappingsGetStored()
        {
            // Arrange
            var sut = new NonGenericTemplate("template");
            var mapping = new StubITemplateMapping();

            // Act
            sut.AddMapping(mapping);

            // Assert
            Assert.Contains<ITemplateMapping>(mapping, sut.TemplateMappings);
            Assert.Equal<int>(1, ((List<ITemplateMapping>)sut.TemplateMappings).Count);
        }
    }
}
